package reflect.engine;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import object.model.JavaFile;
import object.model.JavaVariables;
import object.model.MySQL_TableDDL;
import object.model.TableType;
import reflect.filew.JavaFileWritter;
import system.Sys_Config;

import common.FileControlSet;
import common.ViewSorter;

class JavaModelAnalyser {
	
	private DataBaseStructInfoer infoer = new DataBaseStructInfoer();
	private FileControlSet fcs = new FileControlSet();
	private final String modelLoc = JavaFileWritter.genLocate(Sys_Config.JAVA_MODEL_PACKAGE);
	private final String javaFileSuff = ".java";
	
	public static void main(String[] args){		
		JavaModelAnalyser jma = new JavaModelAnalyser();
		System.out.println(jma.modelLoc);
		List<MySQL_TableDDL> jfL = jma.reverseTableModelDDL();
		jfL.addAll(jma.reverseViewModelDDL());
		for(int i=0;i<jfL.size();i++){
			System.out.println(jfL.get(i).getDropStatement() + ";");
			System.out.println(jfL.get(i).getCreateTable() + ";");
		}
	}
	
	public List<MySQL_TableDDL> reverseTableModelDDL(){
		//reversing tables
		List<MySQL_TableDDL> ddlList = new ArrayList<MySQL_TableDDL>();
		List<File> tableFileList = fcs.findCurrentLevel(modelLoc, "java");
		for(int i=0;i<tableFileList.size();i++){
			JavaFile jf = this.transform(tableFileList.get(i), TableType.TABLE);
			ddlList.add(DDLGenerator.generateTableDDL(jf));
		}		
		return ddlList;
	}
	
	public List<MySQL_TableDDL> reverseViewModelDDL(){
		//reversing views
		List<MySQL_TableDDL> ddlList = new ArrayList<MySQL_TableDDL>();
		List<File> viewFileList = fcs.findCurrentLevel(modelLoc + "view/", "java");
		for(int i=0;i<viewFileList.size();i++){
			MySQL_TableDDL ddl = this.transformViewPreset(viewFileList.get(i));
			ddlList.add(ddl);
		}
		//Sorting
		ddlList = new ViewSorter().getSortedViewsDDL(ddlList);
		return ddlList;
	}
	
	public MySQL_TableDDL transformViewPreset(File file){
		String line = null;
		String packageName = null;
		String className = null;
		String ddl = null;
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Sys_Config.DB_DEFAULT_ENCODING));
			while((line = br.readLine())!=null){
				if(line.startsWith("package")){//file header
					packageName = line.replace("package", "").replace(";", "").trim();
					continue;
				}
				if(line.startsWith("import")){//file header					
					continue;
				}
				if(!line.equalsIgnoreCase("")){
					if(line.startsWith("//DDL:")){
						ddl = line.replace("//DDL:", "").trim();
						continue;
					}else if(line.startsWith("public class")){//class name
						className = this.classLineAnalysis(line);
						break;
					}else{//finished
						continue;
					}
				}else{
					continue;
				}			
			}
			br.close();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		MySQL_TableDDL tbDDL = new MySQL_TableDDL(className,TableType.VIEW);
		tbDDL.setCreateTable(ddl);
		return tbDDL;
	}
	
	public JavaFile transform(File file, TableType type){
		List<JavaVariables> vars = new ArrayList<JavaVariables>();
		List<String> importers = new ArrayList<String>();
		String packageName = null;
		String className = null;
		JavaFile jf = null;			
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Sys_Config.DB_DEFAULT_ENCODING));
			String line = null;
			while((line = br.readLine())!=null){
				if(line.startsWith("package")){//file header
					packageName = line.replace("package", "").replace(";", "").trim();
					continue;
				}
				if(line.startsWith("import")){//file header
					importers.add(this.importLineAnalysis(line));
					continue;
				}
				if(!line.equalsIgnoreCase("")){
					if(line.startsWith("public class")){//class name
						className = this.classLineAnalysis(line);
					}else if(line.contains(";")){//vars
						JavaVariables jv = this.varLineAnalysis(line, importers);
						vars.add(jv);
					}else{//finished
						break;
					}
				}else{
					continue;
				}				
			}
			br.close();
			jf = new JavaFile(packageName, className, vars, type);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return jf;
	}
	
	private String importLineAnalysis(String lineOfImports){
		String imprt = lineOfImports.replaceFirst("import", "").replace(";", "").trim();
		return imprt;
	}
	
	private String classLineAnalysis(String lineOfClass){
		String[] tmp = lineOfClass.split("class");
		String className = "";
		if(tmp.length>2){
			for(int i=1;i<tmp.length;i++){
				className += tmp[i] + ((i==tmp.length-1)?"":"class");
			}
		}else{
			className = tmp[1];
		}
		className = className.substring(0, className.length()-1).trim();
		return className;
	}
	
	private JavaVariables varLineAnalysis(String lineOfVar, List<String> importers) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
		String[] args = lineOfVar.trim().split("//");
		JavaVariables jv = null;
		String accessibility = null;
		String varClassShrt = null;
		String varName = null;
		String varSqlType = null;
		String classFullName = null;
		String condiction = null;
		String key = null;
		if(args.length == 1){//without details
			String[] vas = args[0].trim().split(" ");
			accessibility = vas[0].trim();
			varClassShrt = vas[1].trim();
			varName = vas[2].replace(";", "").trim();
		}else if(args.length == 2){//with details
			String[] vas = args[0].trim().split(" ");
			accessibility = vas[0].trim();
			varClassShrt = vas[1].trim();
			varName = vas[2].replace(";", "").trim();
			String[] details = args[1].trim().split("-");
			varSqlType = details[0].replace("mysqlType:", "").trim();
			if(args[1].contains("Condiction:")){
				condiction = details[1].replace("Condiction:", "").trim();
			}
			if(args[1].contains("KEY:")){
				key = details[2].replace("KEY:", "").trim();
			}
		}else{//error
			//throws
		}
		for(int i=0;i<importers.size();i++){
			String fullType = importers.get(i);
			if(fullType.endsWith(varClassShrt)){
				classFullName = fullType;
				break;
			}
		}		
		jv = new JavaVariables(classFullName, varName, varSqlType, condiction);
		if(key!=null && key.equalsIgnoreCase("PRI")){
			jv.setPrimaryKey(true);
		}
		return jv;
	}
	
}
